﻿using Newtonsoft.Json.Linq;
using Spire.Xls;
using SqlSugar;
using System.Text;
using System.Text.RegularExpressions;
using Wechat_PublicNumber.Common;
using Wechat_PublicNumber.Entity;
using Wechat_PublicNumber.Model;

namespace Wechat_PublicNumber.Repository
{
    /// <summary>
    /// 微信聊天对话仓库
    /// </summary>
    public class WxChatRepository : DataAccess
    {
        [Autowired]
        private WxTemplateRepository _wxTemplateRepository;

        [Autowired]
        private WorkRepository _workRepository;

        [Autowired]
        private WxHttpInvoke _wxHttpInvoke;

        [Autowired]
        private StockRepository _stockRepository;

        [Autowired]
        private CommonHttpInvoke _commonHttpInvoke;

        /// <summary>
        /// 客服接口发送图片
        /// </summary>
        /// <param name="imgPath"></param>
        /// <param name="openID"></param>
        /// <returns></returns>
        public async Task CustomSendImage(string imgPath, string openID)
        {
            var respone = _wxHttpInvoke.UploadMedia(imgPath, Path.GetFileName(imgPath)).Result;

            if (respone is not null)
            {
                await _wxHttpInvoke.CustomSend(new CustomSendRequest() { touser = openID, msgtype = "image", image = new CustomSendRequest_image() { media_id = respone.media_id } });
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="openID"></param>
        /// <returns></returns>
        public async Task<string> ReplyUserMessage(string message, string openID) =>
            GetReplyMessageXML(openID, await ReplyUserAction(message, openID));

        /// <summary>
        /// 微信消息回复
        /// </summary>
        /// <param name="message"></param>
        /// <param name="openID"></param>
        /// <returns></returns>
        public async Task<string> ReplyUserAction(string message, string openID)
        {
            try
            {
                _logger.Info($"用户[{openID}]在{DateTime.Now:yyyy-dd-MM HH:mm:ss}发送了消息：{message}", "UserSendMessage");

                message = message.Replace("：", ":");

                #region 流程写法 暂时不用
                //var nowProcesses = await WXDb.Queryable<WeChatReplyMessageProcesses>()
                //    .Where(s => s.OpenID == openID && (s.UpdateTime.AddMinutes(5) < DateTime.Now || !s.ReplyEnd))
                //    .FirstAsync();
                //if (nowProcesses is not null)
                //{
                //    switch (nowProcesses.ProcessesType)
                //    {
                //        case ReplyMessageProcessesEnum.WeChatTemplateSet:
                //            break;
                //        default:
                //            break;
                //    }
                //} 
                #endregion

                //全匹配直接进行处理
                var keyWordData = await WXDb.Queryable<WeChatChatKeyWord>().Where(s => s.KeyWord == message && s.Type == ChatKeyWordTypeEnum.AllGet && !SqlFunc.IsNullOrEmpty(s.EventType)).FirstAsync();
                if (keyWordData != null) return await ChoiseEventAction(keyWordData.EventType.Value, openID, null, message);

                string whereExpression = $"('{message}' like concat('%',kw.KeyWord,'%'))";

                var keyWordList = await WXDb.Queryable<WeChatChatKeyWord, WeChatKeyWordEvent>((kw, kwe) => new object[]
                    {
                        JoinType.Left,kw.ID==kwe.KeyWordID
                    })
                    .Where((kw, kwe) => SqlFunc.IsNullOrEmpty(kw.EventType))
                    .Where(whereExpression)
                    .Select((kw, kwe) => new
                    {
                        kw.KeyWord,
                        kwe.Type,
                        kwe.EventType,
                        Proportion = kwe.Proportion,
                    }).ToListAsync();

                if (keyWordList.Count > 0)
                {
                    var tempList = keyWordList.GroupBy(s => s.Type).ToList();

                    //获取每个分类的占比
                    var proportionList = tempList.Select(s => new
                    {
                        Type = s.Key,
                        Proportion = s.Sum(ss => ss.Proportion),
                        KeyWordList = s.Select(ss => ss.KeyWord).ToList(),
                        EventType = s.First().EventType,
                    });

                    //获取100的占比
                    var eventData = proportionList.Where(s => s.Proportion == 100).FirstOrDefault();

                    return await ChoiseEventAction(eventData.EventType, openID, eventData.KeyWordList, message);
                }

                return "啊哦，不知道你在说啥";
            }
            catch (Exception ex)
            {
                if (ex.GetType().Name == typeof(WeChatReplyUserException).Name)
                    return ex.Message + "\n查看帮助请输入查看帮助或Help";

                _logger.Error(ex, "ReplyUserContent Error", "ReplyUserMessage");
                return "系统异常，请稍后再试！！";
            }
        }

        /// <summary>
        /// 选择对应执行方法
        /// </summary>
        /// <param name="eventType"></param>
        /// <param name="openID"></param>
        /// <param name="keyWordList"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private async Task<string> ChoiseEventAction(ChatKeyWordEventTypeEnum eventType, string openID, List<string> keyWordList, string message)
        {
            var keyWordEntityList = await WXDb.Queryable<WeChatChatKeyWord>().Where(s => keyWordList.Contains(s.KeyWord)).ToListAsync();

            switch (eventType)
            {
                case ChatKeyWordEventTypeEnum.Chat:
                    return "单扣一个6";
                #region 模板相关
                case ChatKeyWordEventTypeEnum.WeChatTemplateGet:
                    {
                        return await GetTemplateListMessage(openID);
                    }
                case ChatKeyWordEventTypeEnum.WeChatTemplateSet:
                    {
                        return await SetWeChatTemplateStatusMessage(keyWordEntityList, openID);
                    }
                #endregion

                #region 加班相关
                case ChatKeyWordEventTypeEnum.WorkOvertimeGet:
                    {
                        return GetWorkListMessage(openID);
                    }
                case ChatKeyWordEventTypeEnum.WorkOvertimeSet:
                    {
                        return await SetWorkMessage(keyWordEntityList, message, openID);
                    }
                #endregion
                //case ChatKeyWordEventTypeEnum.StockSet:
                //    {
                //        return await SetStockMessage(message, openID);
                //    }
                case ChatKeyWordEventTypeEnum.Helper:
                    {
                        return await GetHelperList();
                    }
                default:
                    return "";
            }
        }

        /// <summary>
        /// 设置是否接收微信模板 Action
        /// </summary>
        /// <param name="keyWordList"></param>
        /// <param name="openID"></param>
        /// <returns></returns>
        /// <exception cref="WeChatReplyUserException"></exception>
        private async Task<string> SetWeChatTemplateStatusMessage(List<WeChatChatKeyWord> keyWordList, string openID)
        {
            var templateData = await _wxTemplateRepository.GetWeChatTemplateByCode(keyWordList.Where(s => s.Type == ChatKeyWordTypeEnum.Param).First().KeyWord);

            if (templateData is null) throw new WeChatReplyUserException("请输入正确的Code");

            var jqy = keyWordList.Where(s => s.Type == ChatKeyWordTypeEnum.JQY).First();

            var status = jqy.Value == "1";

            await _wxTemplateRepository.SetWeChatTemplateStatus(templateData.ID, status, openID);

            return "已执行";
        }

        /// <summary>
        /// 获取微信模板 Action
        /// </summary>
        /// <param name="openID"></param>
        /// <returns></returns>
        private async Task<string> GetTemplateListMessage(string openID)
        {
            var tempList = await WXDb.Queryable<WeChatTemplate, WeChatTemplateSet, WeChatChatKeyWord>((t, ts, p) => new object[]
              {
                JoinType.Left,t.ID==ts.TemplateID && ts.OpenID==openID,
                JoinType.Left,t.ParameterID==p.ID
              }).Where((t, ts, p) => t.Type == WeChatTemplateTypeEnum.All || t.OpenID.Contains(openID))
            .Select((t, ts, p) => new
            {
                p.KeyWord,
                t.Description,
                Status = SqlFunc.IsNull(ts.Status, true)
            }).ToListAsync();

            var returnMessage = new StringBuilder("模板如下：\n");

            foreach (var item in tempList)
            {
                returnMessage.Append($"{item.Description}({item.KeyWord})，状态：{(item.Status ? "✔️" : "❌")}\n");
            }
            returnMessage.Append("\n");
            returnMessage.Append("启用禁用请输入 启用(QY)/禁用(JY)+Code。例如：禁用TQ/JYTQ，两种方式都行\n⚠️注意：禁用后将不再推送该类型的通知");

            return returnMessage.ToString();
        }

        /// <summary>
        /// 获取工作记录 Action
        /// </summary>
        /// <param name="openID"></param>
        /// <param name="year"></param>
        /// <returns></returns>
        private string GetWorkListMessage(string openID, int year = 0)
        {
            Task.Factory.StartNew(() =>
            {
                if (year == 0)
                    year = DateTime.Now.Year;

                var pageCount = 18;

                var path = _workRepository.GetWorkListExcel(openID, year, pageCount).Result;

                pageCount++;

                //Create a Workbook instance
                Workbook workbook = new Workbook();

                //Load an Excel sample document
                workbook.LoadFromFile(path);

                //Get the first worksheet
                Worksheet sheet = workbook.Worksheets[0];

                var totalPage = sheet.Rows.Length % pageCount > 0 ? (sheet.Rows.Length / pageCount) + 1 : sheet.Rows.Length / pageCount;
                if (sheet.Rows.Length % pageCount == 1)
                    totalPage--;

                for (int i = 0; i < totalPage; i++)
                {
                    var lastRow = pageCount * (i + 1);
                    if (sheet.Rows.Length % pageCount == 1 && i == totalPage - 1)
                        lastRow++;

                    //Save the worksheet as an image
                    var jpgPath = path.Replace(Path.GetExtension(path), ".jpg");
                    sheet.ToImage(pageCount * i + 1, 1, lastRow, 4).Save(jpgPath);

                    var respone = _wxHttpInvoke.UploadMedia(jpgPath, Path.GetFileName(jpgPath)).Result;

                    if (respone is not null)
                    {
                        if (_wxHttpInvoke.CustomSend(new CustomSendRequest() { touser = openID, msgtype = "image", image = new CustomSendRequest_image() { media_id = respone.media_id } }).Result == false)
                            break;
                    }
                }
                //$"点击下方链接下载查看：\nhttp://101.42.227.212/WeChat/File/WorkExcel/{Path.GetFileName(path)}";
            });
            //获取成功，以下是加班/调休明细表
            return "";
        }

        /// <summary>
        /// 添加加班/补休数据
        /// </summary>
        /// <param name="keyWordList"></param>
        /// <param name="message"></param>
        /// <param name="openID"></param>
        /// <returns></returns>
        private async Task<string> SetWorkMessage(List<WeChatChatKeyWord> keyWordList, string message, string openID)
        {
            var keyWord = keyWordList.First();

            var jbMessage = message.Replace("：", ":").Replace("，", ",").Replace("小时", "").Split(':')[1];
            //加班：2022-01-02，4小时
            var jbData = jbMessage.Split(",");

            var type = Enum.Parse<WorkTypeEmnu>(keyWord.Value);

            await WXDb.Insertable(new Work() { Type = type, OpenID = openID, WhichDay = DateTime.Parse(jbData[0]), Hours = decimal.Parse(jbData[1]), CreateTime = DateTime.Now }).ExecuteCommandAsync();
            return "已记录";
        }

        #region 注释 功能迁移到wechatWeb
        ///// <summary>
        ///// 添加股票个人设置
        ///// </summary>
        ///// <param name="message"></param>
        ///// <param name="openID"></param>
        ///// <returns></returns>
        //private async Task<string> SetStockMessage(string message, string openID)
        //{
        //    var allSet = message.Replace("，", ",").Split(',');

        //    var stockSplit = allSet[0].Split(":");

        //    if (stockSplit.Length == 1) throw new WeChatReplyUserException("请按照格式输入股票名称或代码");

        //    //初始化Stock
        //    Stock stock = await _stockRepository.GetStockByKeyword(stockSplit[1]);
        //    if (stock is null)
        //    {
        //        var searchStock = await _commonHttpInvoke.GetStockInfo(stockSplit[1]);
        //        if (searchStock == null || searchStock.Count != 1)
        //            throw new WeChatReplyUserException("请输入正确的股票名称或代码");

        //        var oneStock = searchStock.First();
        //        var stockExchange = Regex.Match(oneStock.code, "[SZ|SH]{2}").Value;
        //        var stockCode = Regex.Match(oneStock.code, "[0-9]{6}").Value;

        //        stock = new Stock()
        //        {
        //            CreateTime = DateTime.Now,
        //            BelongStockExchange = Enum.Parse<StockExchange>(stockExchange),
        //            StockName = oneStock.query,
        //            StockCode = stockCode
        //        };
        //    }

        //    //初始化UserStock
        //    UserStock uStock = null;
        //    if (stock.ID != 0)
        //        uStock = await _stockRepository.GetUserStockByOpenID(stock.ID, openID);

        //    if (uStock == null)
        //    {
        //        uStock = new UserStock()
        //        {
        //            OpenID = openID,
        //            CreateTime = DateTime.Now
        //        };
        //    }
        //    else
        //    {
        //        uStock.UpdateTime = DateTime.Now;
        //    }

        //    //获取设置的预警价钱
        //    foreach (var item in allSet)
        //    {
        //        var d = item.Split(':');
        //        if (d.Length == 1) continue;

        //        switch (d[0])
        //        {
        //            case "价格":
        //                uStock.RemindPrice = decimal.TryParse(d[1], out var price) ? price : (uStock.RemindPrice != 0 ? uStock.RemindPrice : 0);
        //                break;
        //            case "涨跌值":
        //                uStock.RemindChg = decimal.TryParse(d[1], out var chg) ? chg : (uStock.RemindChg != 0 ? uStock.RemindChg : 0);
        //                break;
        //            case "涨跌百分比":
        //                uStock.RemindPercent = decimal.TryParse(d[1], out var percent) ? percent : (uStock.RemindPercent != 0 ? uStock.RemindPercent : 0);
        //                break;
        //            default:
        //                break;
        //        }
        //    }

        //    //SaveTable
        //    if (stock.ID != 0)
        //    {
        //        uStock.StockID = stock.ID;
        //        await _stockRepository.SaveUserStock(uStock);
        //    }
        //    else
        //        await _stockRepository.SaveUserStock(stock, uStock);

        //    return "已添加";
        //} 
        #endregion

        /// <summary>
        /// 添加加班/补休数据
        /// </summary>
        /// <returns></returns>
        private async Task<string> GetHelperList()
        {
            return "1、启用禁用推送模板消息：\n启用TQ/QYTQ，禁用TQ/JYTQ\n请输入 HQMB/获取模板 查看模板代码\n2、查看加班调休数据：\nWorkList/Work/加班/补班\n3、添加加班调休数据：\n加班:2022-01-01,2 \n调休和年假替换加班两个字即可，单位小时\n4、添加股票预警推送：\n股票:000630,价格:20.01,涨跌值:0.74,涨跌百分比:3.02\n提供三种监测，需要哪个写就行了，股票可以写名字也可以写code，需要全匹配";
        }

        #region 消息回复XML
        /// <summary>
        /// 文字消息
        /// </summary>
        /// <param name="openID"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public string GetReplyMessageXML(string openID, string message)
        {
            if (string.IsNullOrEmpty(message))
                return "success";

            //回复图片消息
            return $@"<xml>
                       <ToUserName><![CDATA[{openID}]]></ToUserName>
                       <FromUserName><![CDATA[gh_471ba9913446]]></FromUserName>
                       <CreateTime>{(DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000}</CreateTime>
                       <MsgType><![CDATA[text]]></MsgType>
                       <Content><![CDATA[{message}]]></Content>
                      </xml>";
        }

        /// <summary>
        /// 图文消息
        /// </summary>
        /// <param name="openID"></param>
        /// <param name="title">标题</param>
        /// <param name="description">消息描述</param>
        /// <param name="picurl">图片</param>
        /// <param name="url">跳转链接</param>
        /// <returns></returns>
        public string GetReplyMessageXML(string openID, string title, string description, string picurl, string url)
        {
            return $@"<xml>
                      <ToUserName><![CDATA[{openID}]]></ToUserName>
                      <FromUserName><![CDATA[gh_471ba9913446]]></FromUserName>
                      <CreateTime>{(DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000}</CreateTime>
                      <MsgType><![CDATA[news]]></MsgType>
                      <ArticleCount>1</ArticleCount>
                      <Articles>
                        <item>
                          <Title><![CDATA[{title}]]></Title>
                          <Description><![CDATA[{description}]]></Description>
                          <PicUrl><![CDATA[{picurl}]]></PicUrl>
                          <Url><![CDATA[{url}]]></Url>
                        </item>
                      </Articles>
                    </xml>";
        }
        #endregion

        #region Private

        #endregion
    }
}
